/*
Kakine
ActionScript Framework
Copyright © 2011, PUNY, LLC.

This file is part of KAKINE.

KAKINE is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

KAKINE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with KAKINE.  If not, see <http://www.gnu.org/licenses/>.
*/ 
package com.puny.utils
{
	/**
	 * $Revision: 606 $<br/>
	 * Random number utility.<br/>
	 * @example To have <code>50 &lt;= n &lt;100</code>,
	 * <listing>
	 * var n:Number = Random.between(50,100);
	 * </listing>
	 *
	 * @example To have <code>50 &lt; n &lt;=100</code>,
	 * <listing>
	 * var n:Number = Random.between(100,50);
	 * </listing>
	 * 
	 * @example To have <code>s = -1</code> or <code>1</code>,
	 * <listing>
	 * var s:Number = Random.sign();
	 * </listing>
	 * 
	 * @example To have <code>-100 &lt; n &lt;=-50</code> or <code>50 &lt;= n &lt;100</code>, 
	 * <listing>
	 * var n:Number = Random.sign() ~~ Random.between(50,100);
	 * </listing>
	 *
	 * @example To have normal distributed random number,
	 * <listing>
	 * // In this example, 10 is an expectation and 3 is an hwhm. 
	 * // 10 occurs in the highest rate.
	 * // 7(=10-3) or 13(=10+3) occurs in a half rate of 10's occurrence
	 * var gaussian:Gaussian = Random.getGaussian(10,3); 
	 * var f:Number = gaussian.float; 
	 * var n:int = gaussian.integer; 
	 * </listing>
	 * @see com.puny.utils.IGaussian
	 */
	public class Random
	{
		/**
		 * Returned a number <code>n</code> should be ...
		 * <ul>
		 * <li><code>inc &lt;<strong>=</strong> n &lt; exc</code> if <code>inc &lt; exc</code>.<br/></li>
		 * <li><code>exc &lt; n &lt;<strong>=</strong> inc</code> if <code>exc &lt; inc</code><br/></li>
		 * <li>always <code>n = inc</code> if <code>inc = exc</code></li>
		 * </ul>
		 * @param inc included number
		 * @param exc excluded number
		 * @return random number between <code>inc</code> and <code>exc</code>
		 */
		public static function between(inc:Number, exc:Number):Number {
			return Math.random() * (exc - inc) + inc;
		}
		
		/**
		 * @return -1 or 1. 
		 */
		public static function sign():Number {
			return (Math.random() < .5)? -1 : 1;			
		}
		
		/**
		 * Return an integer <code>n</code> should be <code>0 &lt;= n &lt; i</code>
		 * @param i integer 
		 */
		public static function integer(i:int):int {
			return int(Math.random() * i);			
		}
		
//		private static var _sigma:Number;
//		private static var _2sigma2:Number;
//		private static var _2pi:Number = 2 * Math.PI;
//		private static var _g_min:Number;
//		private static var _g_max:Number;
//		public static function gaussianBottomRate(rate:Number):void {
//			_sigma = 1/(Math.sqrt(2*Math.PI) * 1);
//			_2sigma2 = 2* _sigma * _sigma;
//			_g_max = _sigma * Math.sqrt(-2 * Math.log(rate*Math.sqrt(_2pi)*_sigma));
//			_g_min = -_g_max;
//		}
//		
//		public static function gaussian(min:Number,max:Number):Number {
//			var r:Number;
//			var p:Number;
//			do {
//				r = Random.between(_g_min,_g_max);
//				p = 1/(Math.sqrt(_2pi)*_sigma) * Math.exp(-r*r/_2sigma2);
//			} while(p < Math.random());
//			return (r-_g_min)/(_g_max-_g_min)*(max-min)+min;
//		}


		/**
		 * Get normal distributed random numbers generator (Gaussian generator) instance.<br/>
		 * <code>expectation</code> is a valued that would be generated in the highest rate.
		 * <code>expectation+hwhm</code> and <code>expectation-hwhm</code> are values that would be generated in a half of expectation's rate<br/>
		 * <img src="../../../images/gaussian.jpg"/>
		 *
		 * @param expectation the possible returned value in the highest rate
		 * @param hwhm distance from expectation to a possible returned value in a half of the highest rate 
		 * @return Gaussian Generator
		 * @see com.puny.utils.IGaussian
		 * 
		 */
		public static function getGaussian(expectation:Number,hwhm:Number):IGaussian {
			return new GaussianImp(expectation,hwhm);
		}
//		private static const _2pi:Number = Math.PI;
//		private static const _hwhm:Number = 2.35 / 2;
//		private static var _half:Number = _hwhm;
//		private static var _peak:Number = 0;
//		public static function gaussianConfiguration(expectation:Number,hwhm:Number):void {
//			_half = hwhm / _hwhm;
//			_peak = expectation;
//		}
//
//		private static function normalDistribution():Number {
//			var u1:Number = Math.random();
//			var u2:Number = Math.random();
//
//			return _half * Math.sqrt(-2 * Math.log(u1)) * Math.cos(_2pi * u2);
//		}
//		
//		public static function gaussian():Number {
//			return normalDistribution() + _peak;
//		}
//		
//		public static function gaussianInteger():int {
//			var g:Number = normalDistribution();
//			return int(g+((g > 0)? .5 : -.5))+_peak;
//		}
	}
}